//~~tv:20010.20140827 //~~tc: Tealium Custom Container /* Tealium Custom Container Notes: - Add sending code between "Start Tag Sending Code" and "End Tag Sending Code". - Add JavaScript tag library code between "Start Tag Library Code" and "End Tag Library Code". - Add JavaScript code only, do not add HTML code in this file. - Remove any tags from the code you place in this file. Loading external JavaScript files (Loader): - If you need to load an additional external JavaScript file, un-comment the singe-line JavaScript comments ("//") within the following Loader sections near the bottom of this file: - "Start Loader Function Call" - "End Loader Function Call" - "Start Loader Callback Function" - "End Loader Callback Function" - After un-commenting, insert the path to the external JavaScript file you want to load. - Finally, within the Loader callback function, insert the JavaScript code that should run after the external JavaScript file has loaded. */ /* Start Tag Library Code */ /* End Tag Library Code */ //tealium universal tag - utag.sender.custom_container ut4.0.202508160121, Copyright 2025 Tealium.com Inc. All Rights Reserved. try { (function (id, loader) { var u = {}; utag.o[loader].sender[id] = u; // Start Tealium loader 4.32 // Please do not modify if (utag === undefined) { utag = {}; } if (utag.ut === undefined) { utag.ut = {}; } if (utag.ut.loader === undefined) { u.loader = function (o) { var a, b, c, l; a = document; if (o.type === "iframe") { b = a.createElement("iframe"); b.setAttribute("height", "1"); b.setAttribute("width", "1"); b.setAttribute("style", "display:none"); b.setAttribute("src", o.src); } else if (o.type === "img") { utag.DB("Attach img: " + o.src); b = new Image(); b.src = o.src; return; } else { b = a.createElement("script"); b.language = "javascript"; b.type = "text/javascript"; b.async = 1; b.charset = "utf-8"; b.src = o.src; } if (o.id) { b.id = o.id; } if (typeof o.cb === "function") { if (b.addEventListener) { b.addEventListener("load", function () { o.cb(); }, false); } else { b.onreadystatechange = function () { if (this.readyState === "complete" || this.readyState === "loaded") { this.onreadystatechange = null; o.cb(); } }; } } l = o.loc || "head"; c = a.getElementsByTagName(l)[0]; if (c) { utag.DB("Attach to " + l + ": " + o.src); if (l === "script") { c.parentNode.insertBefore(b, c); } else { c.appendChild(b); } } }; } else { u.loader = utag.ut.loader; } // End Tealium loader u.ev = {'view' : 1}; u.initialized = false; u.map={}; u.extend=[function(a,b){ try{ if(1){ /** * @author Montier Elliott * @email montier.elliott@bofa.com * @author Kevin Conway * @email kconway2@bofa.com * @file bactm.plugin.glance * @date 03.02.2022 */ try { (function (parent, name, context, definition) { if (!context || !context[parent] || !Array.prototype.filter) return; context[parent]['plugins']['glance'] = definition(); })('bactm', 'glance', typeof window !== 'undefined' ? window : null, function () { var parent = 'bactm'; var ba = window[parent]; var win = window; var doc = document || {}; var version = '6.48.0'; var ddo = win.digitalData; var LOG_LEVEL = { OFF: 10, FATAL: 5, ERROR: 4, WARN: 3, INFO: 2, DEBUG: 1 }; if (!ddo) return; /** * @method masking * @public */ var masking = function (maskSelectors = window.digitalData.page.attributes.glance.maskSelectors) { try { const allElementsToMask = [] maskSelectors.forEach(selector => { const allOfThisSelector = document.querySelectorAll(selector); allOfThisSelector.forEach(item => allElementsToMask.push(item)); }); allElementsToMask.forEach(element => { element.classList.add("glance_masked") }) } catch (err) { console.log("Error: glance_masked"); bactm.reportError(err); } }; /** * @method addGlanceLoadedClass * @private */ var addGlanceLoadedClass = function () { try { const $glanceButtons = document.querySelectorAll('.glance-button'); for (var i = 0; i < $glanceButtons.length; i++) { $glanceButtons[i].classList.add('glance_available'); } } catch (err) { console.log("Error: glance available"); bactm.reportError(err); } }; /** * @method addGlanceLoadedClass * @private */ var addGlanceNotLoadedClass = function () { try { console.log('bactm.plugin.glance: Glance Not Loaded classes'); const $glanceButtons = document.querySelectorAll('.glance-button'); for (var i = 0; i < $glanceButtons.length; i++) { $glanceButtons[i].classList.add('glance_unavailable'); } } catch (err) { console.log("Error: glance_unavailable"); bactm.reportError(err); } }; /** * @method auth * @param params {object} * @public */ var authSetup = function (params) { console.log('bactm.plugin.glance: Auth Setup called', params); const presencevisitor = new GLANCE.Presence.Visitor({ visitorid: params || digitalData.user.PartyID }); presencevisitor.presence(); presencevisitor.connect(); }; /** * @method unauth * @param params {object} * @public */ var startServer = function (params) { console.log('bactm.plugin.glance: Start Server called', params); }; /** * @method addButtonListeners * @public */ const addButtonListeners = () => { try { var glanceLinks = document.getElementsByClassName('browse-with-specialist'); var cobrowseLink = document.getElementById('cobrowse'); var glanceTrigger = () => GLANCE.Cobrowse.Visitor.showTerms({video: 'off'}); if (window.spaParams) { // Check if sparta page for (let j = 0; j < glanceLinks.length; j++) { glanceLinks[j].addEventListener('click', glanceTrigger); } } else { // Borneo page if (cobrowseLink) { cobrowseLink.addEventListener('click', glanceTrigger) } else { console.log('Glance Button not available.') } } } catch (err) { console.log('Error: Glance Trigger') bactm.reportError(err) } } /** * @method appendGlanceScriptAndPrepCallback * @public */ const appendGlanceScriptAndPrepCallback = (callback) => { const {ws, groupID, src, env} = digitalData?.page?.attributes?.glance; var glance = document.createElement('script'); var head = document.getElementsByTagName('head')[0]; glance.id = 'glance-cobrowse'; glance.type = 'text/javascript'; glance.src = src; glance.setAttribute('data-site', env) glance.setAttribute('data-presence', 'api') // set groupID for prod/staging glance.setAttribute('data-groupid', groupID) // set data-ws for prod/staging glance.setAttribute('data-ws', ws) // once glance script is fully initiated, run our callback functions glance.onload = () => { // we need to wait for the subsequent script loaded from GlanceCobrowseLoader bactm.scriptReady('GlancePresenceVisitor', { childList: true }, callback) }; head.appendChild(glance) } // you can run this code block to set dummy cookies for testing. // Presence: // const bananas = new bactm.Cookies(); // bananas.set('cb_session', 'bananas'); // bananas.set('cb_type', 'presence'); // Code: // const bananas = new bactm.Cookies(); // bananas.set('cb_type', 'code'); /** * @method init * @public */ var _init = function () { ba._log('glance plugin v' + version + ' initializing.', LOG_LEVEL.INFO); const cookies = new ba.Cookies(); const cbTypeCookie = cookies.get('cb_type') const cbSessionCookie = cookies.get('cb_session'); const ddoPartyID = window?.digitalData?.user?.PartyID; const presenceScript = (cb) => { if (!cb) return; const scripts = document.getElementsByTagName('script'); const scriptsArray = Array.from(scripts); const presenceScript = scriptsArray.filter(script => script.src.includes('GlancePresenceVisitor')); if (presenceScript.length > 0) return presenceScript[0].onload = () => { cb(); }; return; } let mobilePartyID = (cbTypeCookie === 'presence' && cbSessionCookie.length > 0) ? cbSessionCookie : false; // prefer to use MDA-passed value from cookie. Else use DDO value, else return false. const evaluatePartyID = () => (mobilePartyID ? mobilePartyID : (ddoPartyID ? ddoPartyID : false)); // trigger masking. Most masking is done via the salesforce glance dashboard, but this has always been around, so not removing it. masking(); // if Glance defined, allow button to show. This is just on one page owned by Global Tenants team. if (!window.GLANCE) return addGlanceNotLoadedClass(); addGlanceLoadedClass(); // mobile partyID passed from MDA, use that, else use DDO partyID, else return false; var glancePartyID = evaluatePartyID(); // proactively show code. This is mobile use-case only. if (cbTypeCookie === 'code' && GLANCE?.Cobrowse?.Visitor?.startSession) { // show code GLANCE.Cobrowse.Visitor.startSession(); // delete cookie so we don't show it again on subsequent page loads. cookies.remove('cb_type'); } // if we have a partyID, wait until presence script fully loaded, then publish presence. if (glancePartyID) return presenceScript(()=> {authSetup(glancePartyID)}) return }; /** * Run init */ try { addButtonListeners(); appendGlanceScriptAndPrepCallback(_init); bactm.on('vendor:glance:auth', authSetup) } catch (e) { bactm.reportError(e) } /** * Public methods */ return { startServer, addButtonListeners, addGlanceLoadedClass }; }); } catch (e) { bactm.reportError(e) } } } catch(e){ utag.DB(e) } }]; u.send = function(a, b) { if (u.ev[a] || u.ev.all !== undefined) { //##UTENABLEDEBUG##utag.DB("send:##UTID##"); var c, d, e, f, i; u.data = { /* Initialize default tag parameter values here */ /* Examples: */ /* "account_id" : "1234567" */ /* "base_url" : "//insert.your.javascript.library.url.here.js" */ /* A value mapped to "account_id" or "base_url" in TiQ will replace these default values. */ }; /* Start Tag-Scoped Extensions Code */ /* Please Do Not Edit This Section */ for(c=0;c